無法接受...
今天來玩個判斷不同顏色的遊戲
import React, { useEffect, useRef, useState } from "react";
const width = 500;
const height = 500;
function ColorGame() {
const canvasRef = useRef(null);
const [canvas, setCanvas] = useState(null);
const [ctx, setCtx] = useState(null);
useEffect(() => {
if (canvasRef.current) {
const c = canvasRef.current;
setCanvas(c);
setCtx(c.getContext("2d"));
}
}, [canvasRef]);
let datas = [];
let step = 0;
let TIME = 30;
let timeDom = document.getElementById("time");
timeDom = { innerText: TIME };
let score = 0;
let scoreDom = document.getElementById("score");
scoreDom = { innerText: score };
let START = false;
let timer;
function startGame() {
START = true;
datas = [];
step = 0;
score = 0;
TIME = 30;
drawGame();
if (!timer) {
timer = window.setInterval(function () {
timeDom.innerText = TIME--;
if (TIME === -1) {
clearInterval(timer);
gameOver();
}
}, 1000);
}
}
function gameOver() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
var text = "Game Over!";
ctx.fillStyle = "red";
ctx.font = "50px sans-serif";
var measure = ctx.measureText(text);
ctx.fillText(
text,
(canvas.width - measure.width) / 2,
(canvas.height - 50) / 2
);
START = false;
}
/**
* @param {} canvas
* @param {} x
* @param {} y
* @description 定位滑鼠位置
*/
function WindowToCanvas(canvas, x, y) {
var box = canvas.getBoundingClientRect();
return {
x: x - box.left * (canvas.width / box.width),
y: y - box.top * (canvas.height / box.height)
};
}
/**
* 根據等級給顏色
* @param {number} step
*/
function getColor(step) {
// 隨機顏色
let random = Math.floor(100 / step);
let color = randomColor(17, 255),
m = color.match(/[\da-z]{2}/g);
// 轉十進位
for (let i = 0; i < m.length; i++) m[i] = parseInt(m[i], 16); //rgb
let specialColor =
getRandomColorNumber(m[0], random) +
getRandomColorNumber(m[1], random) +
getRandomColorNumber(m[2], random);
return ["#" + color, "#" + specialColor];
}
/**
* 隨機取相近色
* @param {number} num
* @param {number} random
*/
function getRandomColorNumber(num, random) {
let temp = Math.floor(num + (Math.random() < 0.5 ? -1 : 1) * random);
if (temp > 255) {
return "ff";
} else if (temp > 16) {
return temp.toString(16);
} else if (temp > 0) {
return "0" + temp.toString(16);
} else {
return "00";
}
}
/**
* 隨機顏色
* @param {number} min 最小值
* @param {number} max 最大值
*/
function randomColor(min, max) {
var r = randomNum(min, max).toString(16);
var g = randomNum(min, max).toString(16);
var b = randomNum(min, max).toString(16);
return r + g + b;
}
/**
* 隨機數量
* @param {number} min 最小值
* @param {number} max 最大值
*/
function randomNum(min, max) {
return Math.floor(Math.random() * (max - min) + min);
}
var isOn = false;
var Rect = function (opt) {
this.x = opt.x;
this.y = opt.y;
this.width = opt.width;
this.height = opt.height;
this.fillStyle = opt.fillStyle;
};
Rect.prototype = {
constructor: Rect,
getPoints: function () {
var p1 = { x: this.x, y: this.y };
var p2 = { x: this.x + this.width, y: this.y };
var p3 = { x: this.x + this.width, y: this.y + this.height };
var p4 = { x: this.x, y: this.y + this.height };
this.points = [p1, p2, p3, p4];
return this.points;
},
createPath: function () {
var points = this.getPoints();
points.forEach(function (point, i) {
ctx[i === 0 ? "moveTo" : "lineTo"](point.x, point.y);
});
if (this.closed) {
ctx.lineTo(this.points[0].x, this.points[0].y);
}
},
updateStyle: function (fillStyle) {
this.fillStyle = fillStyle;
this.isSpecial = true;
return this;
},
draw: function () {
ctx.save();
ctx.fillStyle = this.fillStyle;
ctx.beginPath();
this.createPath();
ctx.closePath();
ctx.stroke();
ctx.fill();
ctx.restore();
},
/**
* @param {Object} p {x: num, y: num}
* @description 判斷使否在範圍內上色
*/
isPointInPath: function (p) {
var isIn = false;
ctx.save();
ctx.beginPath();
this.createPath();
if (ctx.isPointInPath(p.x, p.y)) {
isIn = true;
}
ctx.closePath();
ctx.restore();
return isIn;
}
};
function drawGame() {
datas = []; //清空狀態
ctx.clearRect(0, 0, canvas.width, canvas.height);
step++;
let col; // 設置列數
if (step < 6) {
col = step + 1;
} else if (step < 12) {
col = Math.floor(step / 2) * 2;
} else if (step < 18) {
col = Math.floor(step / 3) * 3;
} else {
col = 16;
}
var blockWidth = ((500 / col).toFixed(2) * 500 - 1) / 500;
var randomCol = Math.floor(col * Math.random());
var randomCell = Math.floor(col * Math.random());
var colorObj = getColor(step);
for (var i = 0; i < col; i++) {
for (var j = 0; j < col; j++) {
var rect = new Rect({
x:
(blockWidth + 5) * i +
(canvas.width - blockWidth * col - (col - 1) * 5) / 2,
y:
(blockWidth + 5) * j +
(canvas.width - blockWidth * col - (col - 1) * 5) / 2,
width: blockWidth,
height: blockWidth,
fillStyle: colorObj[0]
});
if (i === randomCol && j === randomCell) {
rect.updateStyle(colorObj[1]);
}
rect.draw();
datas.push(rect);
}
}
}
const handleStar = () => {
startGame();
};
const handleMouseMove = (e) => {
var pos = WindowToCanvas(canvas, e.clientX, e.clientY);
for (var i = 0; i < datas.length; i++) {
var rect = datas[i];
if (rect.isPointInPath(pos) && rect.isSpecial) {
isOn = true;
break;
} else {
isOn = false;
}
}
};
const handleClickCanvas = () => {
if (!START) return;
if (isOn) {
drawGame();
score++;
scoreDom.innerText = score;
}
};
return (
<div>
<canvas
onMouseMove={handleMouseMove}
onClick={handleClickCanvas}
ref={canvasRef}
width={width}
height={height}
></canvas>
<button onClick={handleStar}>star</button>
</div>
);
}
export default ColorGame;